//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.TridentModel
{
    using System;
    using ER = Microsoft.Research.DataLayer;
    using System.Windows;
    using Microsoft.Research.ScientificWorkflow.TridentUtilities;
    using System.Collections.Generic;
    using System.Workflow.ComponentModel;
    using System.Workflow.Activities;
    using System.Collections.ObjectModel;
    using System.Reflection;
    using System.Globalization;
    using System.Linq;

    public class ModelFactory
    {
        #region Private variables

        /// <summary>
        /// Activity meta data list.
        /// </summary>
        private Collection<ActivityMetadata> activityMetadataList = new Collection<ActivityMetadata>();

        /// <summary>
        /// The list of supported component model activities.
        /// </summary>
        private Collection<string> supportedActivityList;
        #endregion Private variables

        #region Constructor

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="activityMetadataList">
        /// The list of loaded activities.
        /// </param>
        public ModelFactory(Collection<ActivityMetadata> activityMetadataList, Collection<String> supportedActivityList)
        {
            this.activityMetadataList = activityMetadataList;
            this.supportedActivityList = supportedActivityList;
        }

        #endregion Constructor

        #region Public methods

        public BaseModel FetchModelByActivityClass(string activityClass, string uniqueCount, BaseCompositeModel parentModel)
        {
            BaseModel model = null;
            ActivityMetadata metaData = this.GetMetadata(activityClass);
            if (metaData != null)
            {
                model = this.FetchModelByActivityMetadata(metaData, uniqueCount, parentModel);
            }

            return model;
        }

        public BaseModel FetchModelByActivityClass(string activityClass, string uniqueCount, BaseCompositeModel parentModel, Collection<AssemblyInfoModel> associatedAssemblies)
        {
            BaseModel model = null;
            ActivityMetadata metaData = this.GetMetadata(activityClass, associatedAssemblies);
            if (metaData != null)
            {
                model = this.FetchModelByActivityMetadata(metaData, uniqueCount, parentModel);
            }

            return model;
        }

        public BaseModel FetchModelByActivityMetadata(ActivityMetadata metadata, string uniqueCount, BaseCompositeModel parentModel)
        {
            BaseModel model = null;
            switch (metadata.ActivityClass)
            {
                case "TridentBasicActivities.Activities.ForActivity":
                    model = this.FetchForActivityModelByMeta(metadata, uniqueCount);
                    ModelFactory.AssignForActivityModelAttributes(model as ForActivityCompositeModel, parentModel);
                    break;

                case "TridentBasicActivities.Activities.Replicator":
                    model = this.FetchReplicatorActivityModelByMeta(metadata, uniqueCount);
                    ModelFactory.AssignReplicatorActivityModelAttributes(model as ReplicatorActivityCompositeModel, parentModel);
                    break;

                case "TridentBasicActivities.Activities.IFElse":
                    model = this.FetchIfElseCompositeActivityModelByMeta(metadata, uniqueCount);
                    ModelFactory.AssignIfElseActivityModelAttributes(model as IfElseActivityCompositeModel, parentModel);
                    break;

                default:
                    if (metadata.IsComposite)
                    {
                        model = this.FetchCompositeActivityModelByMeta(metadata, uniqueCount);
                        ModelFactory.AssignCompositeActivityModelAttributes(model as CompositeActivityModel, parentModel);
                    }
                    else
                    {
                        model = ModelFactory.FetchSimpleActivityModelByMeta(metadata, uniqueCount);
                        ModelFactory.AssignSimpleActivityModelAttributes(model as SimpleActivityModel, parentModel);
                    }

                    break;
            }

            return model;
        }

        public BaseModel FetchModelByActivitySequence(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentActivity)
        {
            BaseModel model = null;
            if (erActivitySequence != null)
            {
                switch (erActivitySequence.Activity.ActivityClass)
                {
                    case "TridentBasicActivities.Activities.ForActivity":
                        model = this.FetchForActivityModelByActSequence(erActivitySequence, parentActivity);
                        ModelFactory.AssignForActivityModelAttributes(model as ForActivityCompositeModel, parentActivity);
                        break;

                    case "TridentBasicActivities.Activities.Replicator":
                        model = this.FetchReplicatorActivityModelByActSequence(erActivitySequence, parentActivity);
                        ModelFactory.AssignReplicatorActivityModelAttributes(model as ReplicatorActivityCompositeModel, parentActivity);
                        break;

                    case "TridentBasicActivities.Activities.IFElse":
                        model = this.FetchIfElseActivityModelByActSequence(erActivitySequence, parentActivity);
                        ModelFactory.AssignIfElseActivityModelAttributes(model as IfElseActivityCompositeModel, parentActivity);
                        break;

                    case "TridentBasicActivities.Activities.SubSection":
                        model = this.FetchSubsectionModelByActivitySequence(erActivitySequence, parentActivity);
                        ModelFactory.AssignSubsectionModelAttributes(model as TridentSubsectionModel, parentActivity);
                        break;

                    default:
                        if (erActivitySequence.Activity.IsComposite)
                        {
                            if (!this.IsBlackBoxActivity(erActivitySequence))
                            {
                                model = this.FetchCompositeActivityModelByActSequence(erActivitySequence, parentActivity);
                                ModelFactory.AssignCompositeActivityModelAttributes(model as CompositeActivityModel, parentActivity);
                            }
                            else
                            {
                                model = this.FetchCompositeBlackboxModelByActivity(erActivitySequence, parentActivity);
                                ModelFactory.AssignCompositeBlackboxModelAttributes(model as CompositeBlackboxModel, parentActivity);
                            }
                        }
                        else
                        {
                            if (!this.IsBlackBoxActivity(erActivitySequence))
                            {
                                model = ModelFactory.FetchSimpleActivityModelByActSequence(erActivitySequence, parentActivity);
                                ModelFactory.AssignSimpleActivityModelAttributes(model as SimpleActivityModel, parentActivity);
                            }
                            else
                            {
                                model = ModelFactory.FetchSimpleBlackBoxModelByActivity(erActivitySequence, parentActivity);
                                ModelFactory.AssignSimpleBlackboxModelAttributes(model as SimpleBlackboxModel, parentActivity);
                            }
                        }

                        break;
                }
            }

            return model;
        }

        public BaseModel FetchModelByActivity(Activity activity, BaseCompositeModel parentModel)
        {
            BaseModel model = null;
            if (activity != null)
            {
                switch (activity.GetType().ToString())
                {
                    case "TridentBasicActivities.Activities.ForActivity":
                        model = this.FetchForActivityModelByActivity(activity, parentModel);
                        ModelFactory.AssignForActivityModelAttributes(model as ForActivityCompositeModel, parentModel);
                        break;

                    case "TridentBasicActivities.Activities.Replicator":
                        model = this.FetchReplicatorActivityModelByActivity(activity, parentModel);
                        ModelFactory.AssignReplicatorActivityModelAttributes(model as ReplicatorActivityCompositeModel, parentModel);
                        break;

                    case "TridentBasicActivities.Activities.IFElse":
                        model = this.FetchIfElseActivityModelByActivity(activity, parentModel);
                        ModelFactory.AssignIfElseActivityModelAttributes(model as IfElseActivityCompositeModel, parentModel);
                        break;

                    default:
                        if (activity is CompositeActivity)
                        {
                            if (!this.IsBlackBoxActivity(activity))
                            {
                                model = this.FetchCompositeActivityModelByActivity(activity, parentModel);
                                ModelFactory.AssignCompositeActivityModelAttributes(model as CompositeActivityModel, parentModel);
                            }
                            else
                            {
                                model = this.FetchCompositeBlackboxModelByActivity(activity, parentModel);
                                ModelFactory.AssignCompositeBlackboxModelAttributes(model as CompositeBlackboxModel, parentModel);
                            }
                        }
                        else
                        {
                            if (!this.IsBlackBoxActivity(activity))
                            {
                                model = ModelFactory.FetchSimpleActivityModelByActivity(activity, parentModel);
                                ModelFactory.AssignSimpleActivityModelAttributes(model as SimpleActivityModel, parentModel);
                            }
                            else
                            {
                                model = ModelFactory.FetchSimpleBlackBoxModelByActivity(activity, parentModel);
                                ModelFactory.AssignSimpleBlackboxModelAttributes(model as SimpleBlackboxModel, parentModel);
                            }
                        }

                        break;
                }
            }

            return model;
        }

        public BaseModel FetchModelByERActivityId(Guid activityId, ER.Connection connection, BaseCompositeModel parentActivity, string uniqueCount)
        {
            BaseModel model = null;
            try
            {
                ER.Activity updatedActivity = ER.Activity.Load(activityId, connection);
                if (updatedActivity != null)
                {
                    switch (updatedActivity.ActivityClass)
                    {
                        case "TridentBasicActivities.Activities.ForActivity":
                            model = ModelFactory.FetchForActivityModelByErActivity(updatedActivity, parentActivity, uniqueCount);
                            ModelFactory.AssignForActivityModelAttributes(model as ForActivityCompositeModel, parentActivity);
                            break;

                        case "TridentBasicActivities.Activities.Replicator":
                            model = ModelFactory.FetchReplicatorActivityModelByErActivity(updatedActivity, parentActivity, uniqueCount);
                            ModelFactory.AssignReplicatorActivityModelAttributes(model as ReplicatorActivityCompositeModel, parentActivity);
                            break;

                        case "TridentBasicActivities.Activities.IFElse":
                            model = ModelFactory.FetchIfElseActivityModelByErActivity(updatedActivity, parentActivity, uniqueCount);
                            ModelFactory.AssignIfElseActivityModelAttributes(model as IfElseActivityCompositeModel, parentActivity);
                            break;

                        case "TridentBasicActivities.Activities.SubSection":
                            model = ModelFactory.FetchSubsectionModelByErActivity(updatedActivity, parentActivity, uniqueCount);
                            ModelFactory.AssignSubsectionModelAttributes(model as TridentSubsectionModel, parentActivity);
                            break;

                        default:
                            string parentActivityClass = string.Empty;
                            if (parentActivity != null)
                            {
                                parentActivityClass = parentActivity.ActivityClass;
                            }

                            if (updatedActivity.IsComposite)
                            {
                                if (!this.IsBlackBoxActivity(updatedActivity, parentActivityClass))
                                {
                                    model = ModelFactory.FetchCompositeActivityModelByErActivity(updatedActivity, parentActivity, uniqueCount);
                                    ModelFactory.AssignCompositeActivityModelAttributes(model as CompositeActivityModel, parentActivity);
                                }
                                else
                                {
                                    model = ModelFactory.FetchCompositeBlackboxModelByErActivity(updatedActivity, parentActivity, uniqueCount);
                                    ModelFactory.AssignCompositeBlackboxModelAttributes(model as CompositeBlackboxModel, parentActivity);
                                }
                            }
                            else
                            {
                                if (!this.IsBlackBoxActivity(updatedActivity, parentActivityClass))
                                {
                                    model = ModelFactory.FetchSimpleActivityModelByErActivity(updatedActivity, parentActivity, uniqueCount);
                                    ModelFactory.AssignSimpleActivityModelAttributes(model as SimpleActivityModel, parentActivity);
                                }
                                else
                                {
                                    model = ModelFactory.FetchSimpleBlackBoxModelByErActivity(updatedActivity, parentActivity, uniqueCount);
                                    ModelFactory.AssignSimpleBlackboxModelAttributes(model as SimpleBlackboxModel, parentActivity);
                                }
                            }

                            break;
                    }
                }
            }
            catch (ER.RecordNotFoundException)
            {
                // Do not throw exception as the model will be anyway returned as null as indication.
            }

            return model;
        }

        #endregion Public methods

        #region Fetch by metadata

        private static SimpleActivityModel FetchSimpleActivityModelByMeta(ActivityMetadata metaData, string uniqueCount)
        {
            return new SimpleActivityModel(metaData, uniqueCount);
        }

        private CompositeActivityModel FetchCompositeActivityModelByMeta(ActivityMetadata metaData, string uniqueCount)
        {
            CompositeActivityModel compositeModel = new CompositeActivityModel(metaData, uniqueCount);
            if (compositeModel.ActivityClass.Equals("System.Workflow.Activities.ParallelActivity", StringComparison.OrdinalIgnoreCase))
            {
                CompositeActivityModel childSequenceActivity1 = this.FetchModelByActivityClass("System.Workflow.Activities.SequenceActivity",
                    ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture), compositeModel) as CompositeActivityModel;
                childSequenceActivity1.ParentModel = compositeModel;
                childSequenceActivity1.DeleteBehavior = ActivityDeleteBehavior.DeleteChildren;
                childSequenceActivity1.AllowInsertIntoSubsection = false;

                CompositeActivityModel childSequenceActivity2 = this.FetchModelByActivityClass("System.Workflow.Activities.SequenceActivity",
                    ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture), compositeModel) as CompositeActivityModel;
                childSequenceActivity2.ParentModel = compositeModel;
                childSequenceActivity2.DeleteBehavior = ActivityDeleteBehavior.DeleteChildren;
                childSequenceActivity2.AllowInsertIntoSubsection = false;

                compositeModel.Children.Add(childSequenceActivity1);
                compositeModel.Children.Add(childSequenceActivity2);
            }

            return compositeModel;
        }

        private ForActivityCompositeModel FetchForActivityModelByMeta(ActivityMetadata metaData, string uniqueCount)
        {
            ForActivityCompositeModel forModel = new ForActivityCompositeModel(metaData, uniqueCount);
            ActivityMetadata sequenceMetadata = this.GetMetadata("System.Workflow.Activities.SequenceActivity");
            if (sequenceMetadata != null)
            {
                CompositeActivityModel childSequenceActivity = this.FetchCompositeActivityModelByMeta(sequenceMetadata,
                    ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture));
                childSequenceActivity.ParentModel = forModel;
                forModel.Children.Add(childSequenceActivity);
            }

            return forModel;
        }

        private ReplicatorActivityCompositeModel FetchReplicatorActivityModelByMeta(ActivityMetadata metaData, string uniqueCount)
        {
            ReplicatorActivityCompositeModel replicatorModel = new ReplicatorActivityCompositeModel(metaData, uniqueCount);

            // Adding Replicator activity.
            ActivityMetadata replicatorActivityMetadata = this.GetMetadata("System.Workflow.Activities.ReplicatorActivity");
            if (null != replicatorActivityMetadata)
            {
                CompositeActivityModel childReplicatorActivity = 
                    new CompositeActivityModel(replicatorActivityMetadata, 
                    ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture));

                if (null != childReplicatorActivity)
                {
                    childReplicatorActivity.ParentModel = replicatorModel;
                    replicatorModel.Children.Add(childReplicatorActivity);

                    // Adding sequence activity as child to the parent Replicator activity.
                    ActivityMetadata sequenceMetadata = this.GetMetadata("System.Workflow.Activities.SequenceActivity");
                    if (sequenceMetadata != null)
                    {
                        CompositeActivityModel childSequenceActivity = this.FetchCompositeActivityModelByMeta(sequenceMetadata,
                            ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture));
                        if (null != childSequenceActivity)
                        {
                            childSequenceActivity.ParentModel = childReplicatorActivity;
                            childReplicatorActivity.Children.Add(childSequenceActivity);
                        }
                    }
                }
            }

            return replicatorModel;
        }

        private IfElseActivityCompositeModel FetchIfElseCompositeActivityModelByMeta(ActivityMetadata metaData, string uniqueCount)
        {
            IfElseActivityCompositeModel ifElseModel = new IfElseActivityCompositeModel(metaData, uniqueCount);
            if (ifElseModel != null)
            {
                CompositeActivityModel ifConditionActivity = this.FetchModelByActivityClass(
                    "TridentBasicActivities.Activities.IfCondition", ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture), ifElseModel, metaData.AssociatedAssemblies) as CompositeActivityModel;
                ifConditionActivity.ParentModel = ifElseModel;
                ifElseModel.Children.Add(ifConditionActivity);

                ActivityMetadata branchActivityMetadata = this.GetMetadata("System.Workflow.Activities.ParallelActivity");
                if (branchActivityMetadata != null)
                {
                    // Add Branch Activity
                    CompositeActivityModel branchActivity = this.FetchModelByActivityClass(
                        "System.Workflow.Activities.ParallelActivity",
                        ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture),
                        ifElseModel) as CompositeActivityModel;

                    CompositeActivityModel trueBranchActivity;
                    if (branchActivity != null && branchActivity.Children.Count > 1)
                    {
                        trueBranchActivity = branchActivity.Children[0] as CompositeActivityModel;
                    }
                    else
                    {
                        trueBranchActivity = this.FetchModelByActivityClass(
                                               "System.Workflow.Activities.SequenceActivity", 
                                               ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture),
                                               branchActivity) as CompositeActivityModel;
                        branchActivity.Children.Add(trueBranchActivity);
                    }

                    if (null != trueBranchActivity)
                    {
                        CompositeActivityModel iftrueActivity = this.FetchModelByActivityClass(
                            "TridentBasicActivities.Activities.IfTrue", 
                            ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture), 
                            trueBranchActivity, metaData.AssociatedAssemblies) as CompositeActivityModel;
                        if (null != iftrueActivity)
                        {
                            trueBranchActivity.Children.Add(iftrueActivity);
                            iftrueActivity.ParentModel = trueBranchActivity;
                        }

                        trueBranchActivity.ParentModel = branchActivity;
                    }

                    CompositeActivityModel falseBranchActivity;

                    if (branchActivity != null && branchActivity.Children.Count > 1)
                    {
                        falseBranchActivity = branchActivity.Children[1] as CompositeActivityModel; 
                    }
                    else
                    {
                        falseBranchActivity = this.FetchModelByActivityClass(
                            "System.Workflow.Activities.SequenceActivity",
                            ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture), 
                            branchActivity) as CompositeActivityModel;

                        branchActivity.Children.Add(falseBranchActivity);
                    }

                    if (null != falseBranchActivity)
                    {
                        CompositeActivityModel iffalseActivity = this.FetchModelByActivityClass(
                            "TridentBasicActivities.Activities.IfFalse", ActivityUtilities.UniqueCounter.ToString(CultureInfo.InvariantCulture), falseBranchActivity, metaData.AssociatedAssemblies) as CompositeActivityModel;
                        if (null != iffalseActivity)
                        {
                            falseBranchActivity.Children.Add(iffalseActivity);
                            iffalseActivity.ParentModel = falseBranchActivity;
                        }

                        falseBranchActivity.ParentModel = branchActivity;
                    }

                    ifElseModel.Children.Add(branchActivity);
                    branchActivity.ParentModel = ifElseModel;
                }
            }

            return ifElseModel;
        }

        #endregion Fetch by metadata        

        #region Fetch by activity

        private static SimpleActivityModel FetchSimpleActivityModelByActivity(Activity activity, BaseCompositeModel parentModel)
        {
            return new SimpleActivityModel(activity, parentModel);
        }

        private CompositeActivityModel FetchCompositeActivityModelByActivity(Activity activity, BaseCompositeModel parentModel)
        {
            return new CompositeActivityModel(activity, parentModel, this);
        }

        private ForActivityCompositeModel FetchForActivityModelByActivity(Activity activity, BaseCompositeModel parentModel)
        {
            return new ForActivityCompositeModel(activity, parentModel, this);
        }

        private ReplicatorActivityCompositeModel FetchReplicatorActivityModelByActivity(Activity activity, BaseCompositeModel parentModel)
        {
            return new ReplicatorActivityCompositeModel(activity, parentModel, this);
        }

        private IfElseActivityCompositeModel FetchIfElseActivityModelByActivity(Activity activity, BaseCompositeModel parentModel)
        {
            return new IfElseActivityCompositeModel(activity, parentModel, this);
        }

        private static SimpleBlackboxModel FetchSimpleBlackBoxModelByActivity(Activity activity, BaseCompositeModel parentModel)
        {
            return new SimpleBlackboxModel(activity, parentModel);
        }

        private CompositeBlackboxModel FetchCompositeBlackboxModelByActivity(Activity activity, BaseCompositeModel parentModel)
        {
            return new CompositeBlackboxModel(activity, parentModel, this);
        }

        #endregion Fetch by activity

        #region Fetch by activity sequence

        private static SimpleActivityModel FetchSimpleActivityModelByActSequence(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentActivity)
        {
            return new SimpleActivityModel(erActivitySequence, parentActivity);
        }

        private CompositeActivityModel FetchCompositeActivityModelByActSequence(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentActivity)
        {
            return new CompositeActivityModel(erActivitySequence, parentActivity, this);
        }

        private TridentSubsectionModel FetchSubsectionModelByActivitySequence(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentActivity)
        {
            return new TridentSubsectionModel(erActivitySequence, parentActivity, this);
        }

        private ForActivityCompositeModel FetchForActivityModelByActSequence(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentActivity)
        {
            return new ForActivityCompositeModel(erActivitySequence, parentActivity, this);
        }

        private ReplicatorActivityCompositeModel FetchReplicatorActivityModelByActSequence(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentActivity)
        {
            return new ReplicatorActivityCompositeModel(erActivitySequence, parentActivity, this);
        }

        private IfElseActivityCompositeModel FetchIfElseActivityModelByActSequence(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentActivity)
        {
            return new IfElseActivityCompositeModel(erActivitySequence, parentActivity, this);
        }

        private static SimpleBlackboxModel FetchSimpleBlackBoxModelByActivity(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentModel)
        {
            return new SimpleBlackboxModel(erActivitySequence, parentModel);
        }

        private CompositeBlackboxModel FetchCompositeBlackboxModelByActivity(ER.ActivitySequence erActivitySequence, BaseCompositeModel parentModel)
        {
            return new CompositeBlackboxModel(erActivitySequence, parentModel, this);
        }

        #endregion Fetch by activity sequence

        #region Fetch by Er.Activity

        private static SimpleActivityModel FetchSimpleActivityModelByErActivity(ER.Activity activity, BaseCompositeModel parentActivity, string uniqueCount)
        {
            return new SimpleActivityModel(activity, parentActivity, uniqueCount);
        }

        private static CompositeActivityModel FetchCompositeActivityModelByErActivity(ER.Activity activity, BaseCompositeModel parentActivity, string uniqueCount)
        {
            return new CompositeActivityModel(activity, parentActivity, uniqueCount);
        }

        private static TridentSubsectionModel FetchSubsectionModelByErActivity(ER.Activity erActivity, BaseCompositeModel parentActivity, string uniqueCount)
        {
            return new TridentSubsectionModel(erActivity, parentActivity, uniqueCount);
        }

        private static ForActivityCompositeModel FetchForActivityModelByErActivity(ER.Activity activity, BaseCompositeModel parentActivity, string uniqueCount)
        {
            return new ForActivityCompositeModel(activity, parentActivity, uniqueCount);
        }

        private static ReplicatorActivityCompositeModel FetchReplicatorActivityModelByErActivity(ER.Activity activity, BaseCompositeModel parentActivity, string uniqueCount)
        {
            return new ReplicatorActivityCompositeModel(activity, parentActivity, uniqueCount);
        }

        private static IfElseActivityCompositeModel FetchIfElseActivityModelByErActivity(ER.Activity activity, BaseCompositeModel parentActivity, string uniqueCount)
        {
            return new IfElseActivityCompositeModel(activity, parentActivity, uniqueCount);
        }

        private static SimpleBlackboxModel FetchSimpleBlackBoxModelByErActivity(ER.Activity activity, BaseCompositeModel parentModel, string uniqueCount)
        {
            return new SimpleBlackboxModel(activity, parentModel, uniqueCount);
        }

        private static CompositeBlackboxModel FetchCompositeBlackboxModelByErActivity(ER.Activity activity, BaseCompositeModel parentModel, string uniqueCount)
        {
            return new CompositeBlackboxModel(activity, parentModel, uniqueCount);
        }

        #endregion Fetch by Er.Activity

        #region Attributes assignments to models

        private static void AssignSimpleActivityModelAttributes(SimpleActivityModel model, BaseCompositeModel parentModel)
        {
            if (model != null && parentModel != null)
            {
                model.CurrentParameterBindingVisibility = parentModel.CurrentParameterBindingVisibility;
            }
        }

        private static void AssignCompositeActivityModelAttributes(CompositeActivityModel model, BaseCompositeModel parentModel)
        {
            if (model != null && parentModel != null)
            {
                model.CurrentParameterBindingVisibility = parentModel.CurrentParameterBindingVisibility;
            }
        }

        private static void AssignSubsectionModelAttributes(TridentSubsectionModel model, BaseCompositeModel parentModel)
        {
            if (model != null && parentModel != null)
            {
                model.CurrentParameterBindingVisibility = parentModel.CurrentParameterBindingVisibility;
            }
        }

        private static void AssignSimpleBlackboxModelAttributes(SimpleBlackboxModel model, BaseCompositeModel parentModel)
        {
            if (model != null && parentModel != null)
            {
                model.CurrentParameterBindingVisibility = parentModel.CurrentParameterBindingVisibility;
            }
        }

        private static void AssignCompositeBlackboxModelAttributes(CompositeBlackboxModel model, BaseCompositeModel parentModel)
        {
            if (model != null && parentModel != null)
            {
                model.CurrentParameterBindingVisibility = parentModel.CurrentParameterBindingVisibility;
            }
        }

        private static void AssignForActivityModelAttributes(ForActivityCompositeModel model, BaseCompositeModel parentModel)
        {
            if (model != null)
            {
                if (parentModel != null)
                {
                    model.CurrentParameterBindingVisibility = parentModel.CurrentParameterBindingVisibility;
                }

                for (int iterator = 0; iterator < model.Children.Count; iterator++)
                {
                    CompositeActivityModel childSequenceActivity = model.Children[iterator] as CompositeActivityModel;
                    if (childSequenceActivity != null && childSequenceActivity.ActivityClass.Equals(
                        "System.Workflow.Activities.SequenceActivity", StringComparison.OrdinalIgnoreCase))
                    {
                        childSequenceActivity.DeleteBehavior = ActivityDeleteBehavior.DeleteChildren;
                        childSequenceActivity.CurrentParameterBindingVisibility = model.CurrentParameterBindingVisibility;
                        childSequenceActivity.AllowInsertIntoSubsection = false;
                    }
                }
            }
        }

        private static void AssignReplicatorActivityModelAttributes(ReplicatorActivityCompositeModel model, BaseCompositeModel parentModel)
        {
            if (model != null)
            {
                if (parentModel != null)
                {
                    model.CurrentParameterBindingVisibility = parentModel.CurrentParameterBindingVisibility;
                }

                for (int iterator = 0; iterator < model.Children.Count; iterator++)
                {
                    CompositeActivityModel childReplicator = model.Children[iterator] as CompositeActivityModel;
                    if (childReplicator != null && childReplicator.ActivityClass.Equals(
                        "System.Workflow.Activities.ReplicatorActivity", StringComparison.OrdinalIgnoreCase))
                    {
                        childReplicator.DeleteBehavior = ActivityDeleteBehavior.DeleteInvalid;
                        childReplicator.AllowInsertIntoSubsection = false;
                        childReplicator.CurrentParameterBindingVisibility = model.CurrentParameterBindingVisibility;
                        childReplicator.VisibleOnUI = new ActivityModelVisibility(Visibility.Collapsed, Visibility.Collapsed);
                        for (int counter = 0; counter < childReplicator.Children.Count; counter++)
                        {
                            CompositeActivityModel childSeqActivity = childReplicator.Children[counter] as CompositeActivityModel;
                            if (childSeqActivity != null && childSeqActivity.ActivityClass.Equals(
                                "System.Workflow.Activities.SequenceActivity", StringComparison.OrdinalIgnoreCase))
                            {
                                childSeqActivity.DeleteBehavior = ActivityDeleteBehavior.DeleteChildren;
                                childSeqActivity.AllowInsertIntoSubsection = false;
                                childSeqActivity.CurrentParameterBindingVisibility = childReplicator.CurrentParameterBindingVisibility;
                            }
                        }

                        break;
                    }
                }
            }
        }

        private static void AssignIfElseActivityModelAttributes(IfElseActivityCompositeModel model, BaseCompositeModel parentModel)
        {
            if (model != null)
            {
                if (parentModel != null)
                {
                    model.CurrentParameterBindingVisibility = parentModel.CurrentParameterBindingVisibility;
                }

                // Run through the children to find the IfCondition and the BranchConditions.
                for (int iterator = 0; iterator < model.Children.Count; iterator++)
                {
                    CompositeActivityModel child = model.Children[iterator] as CompositeActivityModel;
                    // IfCondition.
                    if (child.ActivityClass.Equals("TridentBasicActivities.Activities.IfCondition", StringComparison.OrdinalIgnoreCase))
                    {
                        child.DeleteBehavior = ActivityDeleteBehavior.DeleteChildren;
                        child.AllowInsertIntoSubsection = false;
                        child.VisibleOnUI = new ActivityModelVisibility(Visibility.Visible, Visibility.Collapsed);                        
                    }
                    // Branch Condition.
                    else if (child.ActivityClass.Equals("System.Workflow.Activities.ParallelActivity", StringComparison.OrdinalIgnoreCase))
                    {
                        child.Label = "Branch";
                        child.AllowInsertIntoSubsection = false;
                        child.DeleteBehavior = ActivityDeleteBehavior.DeleteInvalid;
                        child.CurrentParameterBindingVisibility = model.CurrentParameterBindingVisibility;
                        for (int index = 0; index < child.Children.Count; index++)
                        {
                            // Either the true branch or the false branch.
                            CompositeActivityModel trueOrFalseBranch = child.Children[index] as CompositeActivityModel;
                            trueOrFalseBranch.DeleteBehavior = ActivityDeleteBehavior.DeleteInvalid;
                            if (trueOrFalseBranch.ActivityClass.Equals("System.Workflow.Activities.SequenceActivity", StringComparison.OrdinalIgnoreCase))
                            {
                                trueOrFalseBranch.CurrentParameterBindingVisibility = child.CurrentParameterBindingVisibility;
                                trueOrFalseBranch.AllowInsertIntoSubsection = false;
                                trueOrFalseBranch.VisibleOnUI = new ActivityModelVisibility(Visibility.Collapsed, Visibility.Collapsed);
                                for (int counter = 0; counter < trueOrFalseBranch.Children.Count; counter++)
                                {
                                    // Either the true activity or the false activity.
                                    CompositeActivityModel trueOrFalseActivity = trueOrFalseBranch.Children[counter] as CompositeActivityModel;
                                    if (trueOrFalseActivity.ActivityClass.Equals("TridentBasicActivities.Activities.IfTrue", StringComparison.OrdinalIgnoreCase)
                                        || trueOrFalseActivity.ActivityClass.Equals("TridentBasicActivities.Activities.IfFalse", StringComparison.OrdinalIgnoreCase))
                                    {
                                        trueOrFalseActivity.DeleteBehavior = ActivityDeleteBehavior.DeleteChildren;
                                        trueOrFalseActivity.AllowInsertIntoSubsection = false;
                                        trueOrFalseActivity.CurrentParameterBindingVisibility = trueOrFalseBranch.CurrentParameterBindingVisibility;
                                        trueOrFalseActivity.VisibleOnUI = new ActivityModelVisibility(Visibility.Visible, Visibility.Collapsed);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        #endregion Attributes assignments to models

        #region Misc

        /// <summary>
        /// This is used to get the Activity Meta of the ActivityName.
        ///     The activty meta is retrieved from the list which 
        ///     contains all the ActivityMeta loaded in the left pane.
        /// </summary>
        /// <param name="activityName">Activity Name.</param>
        /// <returns>ActivityMeta for the activity name.</returns>
        public ActivityMetadata GetMetadata(string activityName)
        {
            #region Validation of Arguments

            if (string.IsNullOrEmpty(activityName))
            {
                throw new ArgumentNullException("activityName");
            }

            #endregion

            ActivityMetadata result = null;
            if (this.activityMetadataList != null)
            {
                foreach (ActivityMetadata metadata in this.activityMetadataList)
                {
                    if (metadata.ActivityClass.Equals(activityName))
                    {
                        result = metadata;
                        break;
                    }
                }
            }
            
            return result;
        }

        /// <summary>
        /// This is used to get the Activity Meta of the ActivityName.
        ///     The activty meta is retrieved from the list which 
        ///     contains all the ActivityMeta loaded in the left pane.
        /// </summary>
        /// <param name="activityName">Activity Name.</param>
        /// <returns>ActivityMeta for the activity name.</returns>
        public ActivityMetadata GetMetadata(string activityName, Collection<AssemblyInfoModel> relatedAssemblies)
        {
            #region Validation of Arguments

            if (string.IsNullOrEmpty(activityName))
            {
                throw new ArgumentNullException("activityName");
            }

            #endregion

            ActivityMetadata result = null;
            if (this.activityMetadataList != null)
            {
                foreach (ActivityMetadata metadata in this.activityMetadataList)
                {
                    if (metadata.ActivityClass.Equals(activityName) &&
                        metadata.AssociatedAssemblies.Union(relatedAssemblies, 
                        new AssemblyInfoChecksumComparer()).Count() == relatedAssemblies.Count)
                    {
                        result = metadata;
                        break;
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// This function is used to check whether the activity passed is a BlackBox Acitivy or not.
        /// </summary>
        /// <param name="act">ComponentModel.Activity.</param>
        /// <returns>Whether blackBox activity or not.</returns>
        public bool IsBlackBoxActivity(Activity act)
        {
            System.Type actType = act.GetType();

            if (actType.Namespace.Equals("System.Workflow.ComponentModel") || actType.Namespace.Equals("System.Workflow.Activities"))
            {
                if (actType.Name.Equals("ReplicatorActivity"))
                {
                    if (act.Parent != null && act.Parent.GetType().FullName.Equals("TridentBasicActivities.Activities.Replicator"))
                    {
                        return false;
                    }
                }

                return IsActivitySupported(actType.Name);
            }

            return false;
        }

        /// <summary>
        /// This function is used to check whether the activity passed is a BlackBox Acitivy or not.
        /// </summary>
        /// <param name="act">ComponentModel.Activity.</param>
        /// <returns>Whether blackBox activity or not.</returns>
        public bool IsBlackBoxActivity(ER.ActivitySequence activitySequence)
        {            
            ER.Activity activity = activitySequence.Activity;
            string activityParentClass = string.Empty;
            if (activitySequence.Parent != null)
            {
                activityParentClass = activitySequence.Parent.Activity.ActivityClass;
            }

            return this.IsBlackBoxActivity(activity, activityParentClass);
        }

        /// <summary>
        /// This function is used to check whether the activity passed is a BlackBox Acitivy or not.
        /// </summary>
        /// <param name="act">ComponentModel.Activity.</param>
        /// <returns>Whether blackBox activity or not.</returns>
        public bool IsBlackBoxActivity(ER.Activity activity, string parentActivityClass)
        {
            if (!string.IsNullOrEmpty(parentActivityClass)
                && (activity.ActivityClass.StartsWith("System.Workflow.ComponentModel", StringComparison.OrdinalIgnoreCase)
                || activity.ActivityClass.StartsWith("System.Workflow.Activities", StringComparison.OrdinalIgnoreCase)))
            {
                if (activity.Name.Equals("ReplicatorActivity", StringComparison.OrdinalIgnoreCase))
                {
                    if (parentActivityClass.Equals("TridentBasicActivities.Activities.Replicator", StringComparison.OrdinalIgnoreCase))
                    {
                        return false;
                    }
                }

                return IsActivitySupported(activity.Name);
            }

            return false;
        }

        /// <summary>
        /// Checks whether the builtin activity is supported by trident composer.
        /// </summary>
        /// <param name="activityName">Name of the activity.</param>
        /// <returns>Whether supported or not.</returns>
        private bool IsActivitySupported(string activityName)
        {
            return this.supportedActivityList != null && !this.supportedActivityList.Contains(activityName);
        }
 
        #endregion Misc
    }
}
